Cloudflare WARPのネットワーク
Cloudflare WARPがCloudflare網内のサービスへの接続でクライアントのグローバルIPを隠せていないという問題はよく知られている
マジ?と思うなら curl ifconfig.coしてみよう
何やら変なことをやっていそうなので,調べてみることにした
Cloudflare WARPに接続すると,Cloudflareのネットワークを通ってインターネットに出るためのネットワークインターフェースが作られる
IPv4は172.16.0.2が必ず割り振られているように見える
IPv6にはユニークローカルアドレスが1つ割り振られる
このことから,たとえIPv6であってもNAPTを経由して外に出ているのではないか?という推論が得られる
STUNを使ってローカル・グローバル間でのアドレス・ポートのマッピングを調べる
なんでそんなことするの?と思ってしまうが
世界中で同じコンフィグで接続できるようにすることを考えると割り当てたアドレスからそのままインターネットに出られるみたいなのは現実的ではないかもしれない
一般的なNAPTではwell-knownなポートを使うのを避けようとして小さなポート番号に対して大きなポート番号をマッピングするのでそれを期待して次のようにやる:
$ stunclient --family 6 --localport 2000 stun.l.google.com 19302
code:stun.l.google.com
Binding test: success
Local address: fd01:5ca1:ab1e:8569:ae1c:c772:8ad9:5d62.2000
Mapped address: 2a09:bac0:22::825:2bde.37886
ということで外に出るときにNAPTしていることがわかる
ではなぜこのような現象が起きているのか?
Cloudflare WARPにおいてインターフェースに割り当てられるIPアドレスは(IPv4v6を問わず)衝突しても構わないように設計されている
サードパーティの(怪しい)WireGuardの設定を吐くスクリプトではIPv6アドレスも同じになっている
この場合網内のルーティングをどうするのという問題が出てくる
この解答が https://blog.cloudflare.com/ja-jp/warp-technical-challenges-ja-jp/ に書いてある
ルーティングの識別子を WireGuard のヘッダに埋め込むといった興味深い話があるが,送信元 IP アドレスはコネクションの判別の役に立たないという部分が重要そう
識別子がなくとも動作するので,NAPT 自体は別の値を送信元 IP の代わりとなる識別子として使っていると考えるのが自然そう
ルーティングが正しければreceiver_indexで識別できるのか?
この下妄想
この状態でどのように網内のルーティングを行うのかという話だが,WireGuardのパケットの送信元IP(つまり,真のクライアントIPアドレス)を用いているのではないか?
実現方法はいろいろ想像できると思うが,一つ例を考えてみる
engage.cloudflareclient.comでWireGuardを終端し
外向きならばクライアントのアドレスを使ってNAPTを通して外に出し
内向きならばsrcをクライアントのアドレスにしてネットワークに投げる
何かしらの理由で内部のL7LBはIPアドレスを隠せないようになっていると考えるのが自然だし,そうなっているとしたら↑のような構成になっているんじゃないか
反論一覧
これだとするとプライベートネットワークのIPアドレスを使うようにNAPTしてから内側に投げればいいんじゃないですか?
Cloudflare WARPって移動しても接続が切れないようになっていたはずだけど,この方法だとIPアドレスが変化したタイミングで全てが変わってしまいませんか?
HTTPを使ってCloudflare網外と通信しながら接続先を切り替えたところ,WARPの再接続の後コネクションは切れることなく1秒程度で再び通信するようになった
Private Keyか何かを使って接続先を識別しつつNAPTテーブルのエントリを書き変えるみたいなことをしてそう
メモ
STUNでマッピングを得た後,すかさず異なるSTUNサーバーにアクセスしても同じマッピングが得られたのでEndpoint-Independent Mappingであることがわかる
$ stunclient --family 6 --localport 2000 stun2.l.google.com 19302
code:stun2.l.google.com
Binding test: success
Local address: fd01:5ca1:ab1e:8569:ae1c:c772:8ad9:5d62.2000
Mapped address: 2a09:bac0:22::825:2bde.37886
UDPホールパンチングの成功率を上げるのに効果があるかも
IPv4でも同様のNAPTが行われている
一種のCGNであるが,アドレス共有が行われているかどうかまでは分からなかった
これらのポートで必ず異なるポートにマッピングされるのは0-9023までのようだ